home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 4 / BBS in a Box - Macintosh - Volume IV (January 1992) (BBS in a Box).iso / Files / Prog / N-P / Patch Ext.sea / patch < prev    next >
Encoding:
Text File  |  1991-05-04  |  8.9 KB  |  383 lines  |  [TEXT/PCXT]

  1. Path: ooc.uva.nl!hp4nl!mcsun!uunet!crdgw1!uakari.primate.wisc.edu!sdd.hp.com!elroy.jpl.nasa.gov!ncar!gatech!udel!haven.umd.edu!ni.umd.edu!ni.umd.edu!zben
  2. From: zben@ni.umd.edu (Ben Cranston)
  3. Newsgroups: comp.sys.mac.programmer
  4. Subject: MPW tool to patch resources or files
  5. Keywords: MPW Patch
  6. Message-ID: <1991Apr27.010549.20391@ni.umd.edu>
  7. Date: 27 Apr 91 01:05:49 GMT
  8. Sender: usenet@ni.umd.edu (USENET News System)
  9. Organization: University of Maryland at College Park
  10. Lines: 369
  11. Nntp-Posting-Host: ni.umd.edu
  12.  
  13. There were some simple example MPW tools in this month's MacTutor.  I had
  14. never realized it was that easy to write a tool!  Here is a tool that can
  15. be used to "patch" a resource or a data fork with either inline hex data,
  16. the contents of another resource, or the contents of another data fork.
  17. For example, the "command-F" patches for LaserWriter 6.0.1 can be done
  18. with this command:
  19.  
  20.  Patch LaserWriter PDEF(125) <command-d>
  21.     $c78:51 $c7c:50 $c84:50 $c8c:51 $c9a:50 $e9e:6038 $1860:60
  22.  
  23. Some of the diagnostics are a bit wrong but I think a diagnostic is given
  24. for every error case.  Also there is some debug printout you can take out
  25. when you trust it.  There is a neat hex dump routine buried in here too!
  26.  
  27.  
  28. /* MPW tool to "Patch" data or resource fork of file
  29.  *
  30.  * For usage notes see below...
  31.  *
  32.  * Ben Cranston <zben@ni.umd.edu>
  33.  * University of Maryland at College Park
  34.  * 910419
  35.  */
  36.  
  37. #include <CType.h>
  38. #include <ErrMgr.h>
  39. #include <Files.h>
  40. #include <Memory.h>
  41. #include <Resources.h>
  42. #include <StdIO.h>
  43. #include <String.h>
  44.  
  45. #define P(x) fprintf(stderr,"%s%s\n",progname,x);
  46. #define Q(x) fprintf(stderr,"%s\n",x);
  47.  
  48. char    *progname;
  49.  
  50. usage()
  51. {
  52. P(": Usage:                            ")
  53. P(" file offset:hexdata                        ")
  54. P(" file offset infile inoffset:length                ")
  55. P(" file offset infile resource                    ")
  56. Q("");
  57. P(" file resource offset:hexdata                ")
  58. P(" file resource offset infile inoffset:length            ")
  59. P(" file resource offset infile resource            ")
  60. Q("");
  61. Q("where resource is  restype(resnum)  or  restype@resname    ")
  62. }
  63.  
  64. /*
  65.  * Test for valid hexadecimal digit.
  66.  */
  67.  
  68. #define ishex(x) (isascii(x)&&isxdigit(x))
  69.  
  70. /*
  71.  * Integer value (0-15) for hexadecimal digit.
  72.  */
  73.  
  74. #define toint(x) ((x)<='9'?(x)-'0':(x)<='F'?(x)-'A'+10:(x)-'a'+10)
  75.  
  76. /*
  77.  * Print out system string for a particular error code.
  78.  */
  79.  
  80. syserr(short errcode)
  81. {
  82.     char    errmsg[256];
  83.  
  84.     GetSysErrText(errcode,errmsg);
  85.     fprintf(stderr,"# %s\n",errmsg);
  86. }
  87.  
  88. /*
  89.  * Diagnose syntax error on call to this tool.
  90.  */
  91.  
  92. syntax(char *s)
  93. {
  94.     fprintf(stderr,"%s - %s\n",progname,s);
  95.     exit(1);
  96. }
  97.  
  98. /*
  99.  * Diagnose file access problems.
  100.  */
  101.  
  102. cant(char *diag, char *fname, short errcode)
  103. {
  104.     fprintf(stderr,"# %s - Can't %s : %P\n",progname,diag,fname);
  105.     syserr(errcode);
  106.     exit(2);
  107. }
  108.  
  109. /*
  110.  * Show arguments to this program.
  111.  */
  112.  
  113. dumpargs(int argc, char **argv)
  114. {
  115.     short i;
  116.  
  117.     fprintf(stderr,"argc = %d\n",argc);
  118.     for (i=0 ; i<argc; i++)
  119.         fprintf(stderr,"argv[%d] = \"%s\"\n",i,argv[i]);
  120. }
  121.  
  122. /*
  123.  * Dump area in hexadecimal and readable formats.
  124.  */
  125.  
  126. hexdump(int num, char *buf)
  127. {
  128.         short rx,cx;
  129.         char chr;
  130.         char vr[17];
  131.  
  132.         for ( rx=0 ; rx<num ; rx+=16 ) {
  133.         fprintf(stderr,"%03X  ",rx);
  134.                 for ( cx=0 ; cx<16 ; cx++ ) {
  135.                         if ( (rx+cx) < num ) {
  136.                                 chr = buf[rx+cx];
  137.                                 fprintf(stderr,"%02X ",chr&0xFF);
  138.                                 vr[cx] = (isascii(chr)&&isprint(chr))?chr:'.';
  139.                         } else {
  140.                                 fprintf(stderr,"   ");
  141.                                 vr[cx] = ' ';
  142.                         }
  143.                 }
  144.                 vr[16] = 0;
  145.                 fprintf(stderr," %s\n",vr);
  146.         }
  147. }
  148.  
  149. /*
  150.  * Scan and convert integer, either decimal or $hex.
  151.  */
  152.  
  153. int getnum(char *s, char t)
  154. {
  155.     int    acc = 0;
  156.     short    sign = 1;
  157.  
  158.     if ('$' == (*s)) {
  159.         s++;
  160.         while ( ishex(*s) ) {
  161.             acc = (acc<<4) | toint(*s);
  162.             s++;
  163.         }
  164.     } else {
  165.         if ('-' == (*s)) {
  166.             s++;
  167.             sign = -1;
  168.         }
  169.         while ( (isascii(*s)&&isdigit(*s)) ) {
  170.             acc = 10*acc + (*s) - '0';
  171.             s++;
  172.         }
  173.         acc = sign*acc;
  174.     }
  175.  
  176.     if (t!=0) {
  177.         if (t!=(*s))
  178.             syntax("missing field terminator");
  179.         else
  180.             s++;
  181.     }
  182.  
  183.     if (*s)
  184.         syntax("bad character in integer field");
  185.     return(acc);
  186. }
  187.  
  188. /*
  189.  * Scan a resource designator and read in the designaged resource.
  190.  * This is called both to get resource data for a patch source
  191.  * and to get in a resource that is itself to be patched.
  192.  *
  193.  * Formats are:
  194.  *    PDEF(125)
  195.  *    $50444546(125)        # same, but restype specified in hex
  196.  *    PDEF@resourcename    # resource designated by name rather than number
  197.  */
  198.  
  199. short
  200. getres(char *fname, char *sfield, short perms, short *rfnum, Handle *rshand)
  201. {
  202.     char    *sp;
  203.     short    which, rsnum, status;
  204.     OSType    rstype;
  205.     char    buffer[6], rsname[256];
  206.  
  207.     if (sp = strchr(sfield,'(') ) {
  208.         which = 1;
  209.         rsnum = getnum(sp+1,')');
  210.     } else if (sp = strchr(sfield,'@') ) {
  211.         which = 0;
  212.         rsname[0] = strlen(sp+1);
  213.         BlockMove(sp+1,&rsname[1],rsname[0]);
  214.     } else
  215.         return(0);
  216.  
  217.     (*sp) = 0;
  218.     if ('$' == (*sfield) )
  219.         rstype = getnum(sfield,0);
  220.     else if (4 >= (status = sp-sfield) ) {
  221.         rstype = (OSType) '    ';
  222.         BlockMove(sfield,(char *)&rstype,status);
  223.     } else
  224.         syntax("bad resource type field");
  225.  
  226.     SetResLoad(false);
  227.     (*rfnum) = OpenRFPerm(fname,0,perms);
  228.     SetResLoad(true);
  229.     if (0 > (*rfnum) )
  230.         cant("open (resource fork of) file",fname,ResError());
  231.  
  232.     if (which)
  233.         (*rshand) = Get1Resource(rstype,rsnum);
  234.     else
  235.         (*rshand) = Get1NamedResource(rstype,rsname);
  236.  
  237.     if (0 == (*rshand) ) {
  238.         *(OSType *)&buffer = rstype;
  239.         buffer[4] = 0;
  240.         if (which)
  241.             fprintf(stderr,"# %s - Can't load resource : %P %s %d\n",
  242.                 progname,fname,buffer,rsnum);
  243.         else
  244.             fprintf(stderr,"# %s - Can't load resource : %P %s %P\n",
  245.                 progname,fname,buffer,rsname);
  246.         if (0 == (status=ResError()) )
  247.             fprintf(stderr,"# No ResError worth mentioning...\n");
  248.         else
  249.             syserr(status);
  250.         exit(2);
  251.     }
  252.  
  253.     return(1);
  254. }
  255.  
  256. main(int argc, char **argv)
  257. {
  258.     short    rfnum, rrfnum, status;
  259.     char    *sp;
  260.     int    length, offset, roffset, xflen;
  261.     char    fname[256];
  262.     char    bigbuf[1024];
  263.     Handle    rshand, rrshand;
  264.  
  265. /*    dumpargs(argc,argv);    */
  266.     progname = argv[0];
  267.     argc--, argv++;
  268.     if (argc < 2) {
  269.         usage();
  270.         exit(1);
  271.     }
  272.     
  273.     fname[0] = strlen(argv[0]);
  274.     BlockMove(argv[0],&fname[1],fname[0]);
  275. /*
  276.  * Open file (and possibly resource) to be patched
  277.  */
  278.     if ( getres(fname,argv[1],fsRdWrPerm,&rfnum,&rshand) )
  279.         argc--, argv++;
  280.     else {
  281.         if ( 0 > (status = FSOpen(fname,0,&rfnum)) )
  282.             cant("open (data fork of) file",fname,status);
  283.         rshand = (Handle) 0;
  284.     }
  285.     argc--, argv++;
  286.     
  287.     do {
  288. /*
  289.  * Get patch
  290.  */
  291.         if (0 > argc)
  292.             syntax("missing patch field!");
  293.         if (sp = strchr(argv[0],':') ) {
  294.             *sp = 0;
  295.             offset = getnum(argv[0],0);
  296.             length = 0;
  297.             while ( *(sp+1) ) {
  298.                 if (ishex(*(sp+1)) && ishex(*(sp+2))) {
  299.                     bigbuf[length++] =
  300.                         (toint(*(sp+1))<<4) + toint(*(sp+2));
  301.                     sp += 2;
  302.                 } else
  303.                     syntax("error in hex input data");
  304.             }
  305.         } else {
  306.             offset = getnum(argv[0],0);
  307.             argc--, argv++;
  308.             if (0 > argc)
  309.                 syntax("missing patch file!");
  310.             fname[0] = strlen(argv[0]);
  311.             BlockMove(argv[0],&fname[1],fname[0]);
  312.             if ( getres(fname,argv[1],fsRdPerm,&rrfnum,&rrshand) ) {
  313.                 length = GetHandleSize(rrshand);
  314.                 if ( sizeof(bigbuf) < length )
  315.                     syntax("resource too big!!!");
  316.                 BlockMove(*rrshand,bigbuf,length);
  317.                 CloseResFile(rrfnum);
  318.             } else if (sp = strchr(argv[1],':') ) {
  319.                 *sp = 0;
  320.                 roffset = getnum(argv[1],0);
  321.                 length = getnum(sp+1,0);
  322.                 if (0 > (status = FSOpen(fname,0,&rrfnum)) )
  323.                     cant("open (data fork of) file",fname,status);
  324.                 if (0 > (status = SetFPos(rrfnum,fsFromStart,roffset)) )
  325.                     cant("reposition within file",fname,status);
  326.                 xflen = length;
  327.                 if (0 > (status = FSRead(rrfnum,&xflen,bigbuf)) )
  328.                     cant("read (data fork of) file",fname,status);
  329.                 if (xflen != length) {
  330.                     fprintf(stderr,"data short read %d\n",xflen);
  331.                     length = xflen;
  332.                 }
  333.                 if (0 > (status = FSClose(rrfnum)) )
  334.                     cant("close (data fork of) file",fname,status);
  335.             } else
  336.                 syntax("missing : in offset:length field");
  337.             argc--, argv++;
  338.         }
  339.         argc--, argv++;
  340.  
  341.         fprintf(stderr,"offset = %d\n",offset);
  342.         fprintf(stderr,"length = %d\n",length);
  343.         hexdump(length,bigbuf);
  344. /*
  345.  * Apply patch
  346.  */
  347.         if (rshand) {
  348.             if ( (offset+length) > GetHandleSize(rshand) ) {
  349.                 SetHandleSize(rshand,offset+length);
  350.                 if (noErr != (status=MemError()) ) {
  351.                     fprintf(stderr,"# Could not expand handle\n");
  352.                     syserr(status);
  353.                     exit(2);
  354.                 }
  355.             }
  356.             BlockMove(bigbuf,(offset+*rshand),length);
  357.         } else {
  358.             if (0 > (status = SetFPos(rfnum,fsFromStart,offset)) )
  359.                 cant("reposition within file",fname,status);
  360.             xflen = length;
  361.             if (0 > (status = FSWrite(rfnum,&xflen,bigbuf)) )
  362.                 cant("write to (data fork of) file",fname,status);
  363.             if (xflen != length)
  364.                 fprintf(stderr,"data short write %d\n",xflen);
  365.         }
  366.  
  367.         fprintf(stderr,"at end, argc = %d\n",argc);
  368.     } while (0 < argc);
  369. /*
  370.  * Close file and/or resource fork
  371.  */
  372.     if (rshand) {
  373.         ChangedResource(rshand);
  374.         CloseResFile(rfnum);
  375.     } else {
  376.         if (0 > (status = FSClose(rfnum)) )
  377.             cant("close (data fork of) file",fname,status);
  378.     }
  379.  
  380.     exit(0);
  381. }
  382.  
  383.